---
title: Extract pages
summary: Validates a source PDF and extracts a caller-specified set of page ranges into a new document.
status: draft
owner: Not determined from source
last_reviewed: 2026-09-17
library: PdfAPI
reference_type: embedded
operation_id: OP-EXTRACT-PAGES
trigger: Client submits a POST v1/extract request with an ExtractPagesRequest body
---

# OP-EXTRACT-PAGES: Extract pages

Validates that the source document is a real PDF, then extracts the requested page ranges (with clamping, skipping, and reversal semantics) into a new output document.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-EXTRACT-PAGES |
| **Trigger** | Client submits `POST v1/extract` with an `ExtractPagesRequest` body |
| **Entry endpoint** | [`POST v1/extract`](../endpoints/extract-controller.md#post-v1%2Fextract) |
| **Owning component** | `ExtractController.Extract(ExtractPagesRequest)` → `IPdfService.ExtractPages(request)` |
| **Inputs** | `ExtractPagesRequest` (a `DocumentRange` pairing a source `Document` with one or more `PageRange` values), `SourceSystemId` |
| **Outputs** | `PdfResult` (`Status`, `Message`, `Document`, `TrackingId`); a `PDFTracking` row created/updated |
| **Failure response** | Caught exceptions are logged and returned as `Ok(new PdfResult(message))` — HTTP `200` |

## Steps

1. The action wraps the call in `try`/`catch` ([BR-PDFAPI-017](../business-rules.md#br-pdfapi-017-processing-failures-return-200-with-a-pdfresult)).
   - On any exception: `_logService.LogException("pdfapi", "Extract", "<detail>", ex)`, then `Ok(new PdfResult(ex.Message, request: request))` — HTTP `200`, produced by the action's own `catch` block.
2. If tracking is enabled (default, or forced on by `SendHeatEmailOnFailure`, [BR-PDFAPI-010](../business-rules.md#br-pdfapi-010-tracking-forced-on-with-heat-email)), `PdfTrackingService.CreateTrackingRecord` inserts a `PDFTracking` row.
3. When `pdfapi.saveInputToTemp` is enabled, the inbound document is written to temporary storage before extraction ([BR-PDFAPI-016](../business-rules.md#br-pdfapi-016-save-input-to-temp-storage)).
4. `PdfClientService.ValidatePdf(request.DocumentRange.Document)` validates the `%PDF-` file signature before any extraction work ([BR-PDFAPI-004](../business-rules.md#br-pdfapi-004-extraction-requires-pdf-validation), [BR-PDFAPI-005](../business-rules.md#br-pdfapi-005-pdf-validity-by-file-signature)).
   - On failure: a `PdfException` is thrown reporting that the file is not a valid PDF document (exact message text is not visible in this repository) and caught by step 1's `try`/`catch` — HTTP `200` with a failure `PdfResult`.

   This validation is implemented in `PdfAPI.Core` (`PdfClientService.ValidatePdf`), documented in full at [Validate PDF bytes](../../../libraries/pdfapi-core/operations/op-01-validate-pdf-bytes.md) (OP-01); its behavior is summarized here only as observed on this request path.

   > **Origin:** The PDF-signature validation behavior described in this step is implemented in
   > `PdfAPI.Core`, not in `PdfAPI`. See the linked operation page for the full delegated logic.
5. `PdfExtractor.Extract` applies each page range: ranges are clamped to the document's page count, out-of-range ranges are skipped rather than erroring, descending ranges extract pages in reverse order, and a single `IsOriginal` range short-circuits and returns the original file untouched ([BR-PDFAPI-018](../business-rules.md#br-pdfapi-018-page-range-clamping-and-reversal)).

   This extraction logic is implemented in `PdfApi.SyncFusionCore` (`PdfExtractor.Extract`), documented in full at [Extract page ranges from a PDF](../../../libraries/pdfapi-syncfusioncore/operations/extract-page-ranges-from-pdf.md) (OP-SFC-011); its behavior is summarized here only as observed on this request path.

   > **Origin:** The page-range clamping, skipping, and reversal behavior described in this step
   > is implemented in `PdfApi.SyncFusionCore`, not in `PdfAPI`. See the linked operation page for
   > the full delegated logic.
6. `SourceConversionType.Pdf` is stamped on the result and `SourceSystemId` is parsed into `ImageId`.
7. `FinalizeResult` stamps `TrackingId`, `PdfProcessorType`, `FilePath`, then persists the terminal tracking status via `PdfTrackingService.UpdateTrackingRecord`.
8. The controller returns `Ok(result)` — HTTP `200` regardless of whether extraction succeeded or failed.

## Process flow

The following diagram shows the validation, extraction, and tracking sequence for a page-extraction request.

```mermaid
flowchart TD
    A["POST v1/extract"] --> B["Create tracking record"]
    B --> C["ValidatePdf: check file signature"]
    C -->|Invalid| D["PdfException caught:<br>failure PdfResult, 200"]
    C -->|Valid| E["PdfExtractor.Extract applies page ranges"]
    E --> F["Stamp SourceConversionType and ImageId"]
    F --> G["FinalizeResult: persist terminal status"]
    G --> H["Ok result"]
```

## Transaction and side effects

| Aspect | Finding |
| --- | --- |
| Unit of work | `IUnitOfWorkFactory("oracle")`, `InstancePerRequest` |
| Commit point | `PdfTrackingService.CreateTrackingRecord` and `UpdateTrackingRecord`, each bracketed by `_uow.Begin()`/`_uow.Commit()` |
| Records written | `PDFTracking` ([data model](../data-model.md#pdftracking-properties-observed-in-use)) |
| Downstream calls | None (extraction is a fully local, single-request operation) |
| Repeat-call behavior | Each call creates a new tracking record; not idempotent |

## Logging

| Surface | Written content |
| --- | --- |
| `ILogService.LogException` | `"pdfapi"`, `"Extract"`, and exception detail, on any caught failure |

## Error handling

- Non-PDF source document: `PdfException` thrown by `PdfClientService.ValidatePdf`, caught in the action, logged, returned as `Ok(new PdfResult(message))` — HTTP `200` ([BR-PDFAPI-017](../business-rules.md#br-pdfapi-017-processing-failures-return-200-with-a-pdfresult)).
- Out-of-range or descending page ranges: not an error — tolerated per [BR-PDFAPI-018](../business-rules.md#br-pdfapi-018-page-range-clamping-and-reversal).

## Related documentation
- [API index](../index.md)
- [Overview](../overview.md)
- [Architecture](../architecture.md)
- [Endpoints](../endpoints.md)
- [Authentication and authorization](../authentication-authorization.md)
- [Dependencies](../dependencies.md)
- [Configuration](../configuration.md)
- [Operations and processes](../operations-processes.md)
- [Business rules](../business-rules.md)
- [Data model](../data-model.md)
- [Operational runbook](../operational-runbook.md)
- [Tech debt](../tech-debt.md)

## Sources
- PdfAPI\Controllers\v1\ExtractController.cs
- PdfAPI\Services\PdfService.cs
- PdfAPI\Services\PdfTrackingService.cs
- PdfAPI.Core\Services\PdfClientService.cs
- PdfAPI.Core\Extract\PageRange.cs
- PdfApi.SyncFusionCore\Extract\PdfExtractor.cs
